1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package sun.security.krb5;
33
34 import sun.security.krb5.internal.*;
35 import sun.security.util.*;
36 import java.net.*;
37 import java.util.Vector;
38 import java.io.IOException;
39 import java.math.BigInteger;
40 import sun.security.krb5.internal.ccache.CCacheOutputStream;
41 import sun.security.krb5.internal.util.KerberosString;
42
43
44
45
46
47 public class PrincipalName
48 implements Cloneable {
49
50
51
52
53
54
55 public static final int KRB_NT_UNKNOWN = 0;
56
57
58
59
60 public static final int KRB_NT_PRINCIPAL = 1;
61
62
63
64
65 public static final int KRB_NT_SRV_INST = 2;
66
67
68
69
70 public static final int KRB_NT_SRV_HST = 3;
71
72
73
74
75 public static final int KRB_NT_SRV_XHST = 4;
76
77
78
79
80 public static final int KRB_NT_UID = 5;
81
82
83
84
85
86
87 public static final String TGS_DEFAULT_SRV_NAME = "krbtgt";
88 public static final int TGS_DEFAULT_NT = KRB_NT_SRV_INST;
89
90 public static final char NAME_COMPONENT_SEPARATOR = '/';
91 public static final char NAME_REALM_SEPARATOR = '@';
92 public static final char REALM_COMPONENT_SEPARATOR = '.';
93
94 public static final String NAME_COMPONENT_SEPARATOR_STR = "/";
95 public static final String NAME_REALM_SEPARATOR_STR = "@";
96 public static final String REALM_COMPONENT_SEPARATOR_STR = ".";
97
98 private int nameType;
99 private String[] nameStrings;
100
101 private Realm nameRealm;
102
103
104
105 private String salt = null;
106
107 protected PrincipalName() {
108 }
109
110 public PrincipalName(String[] nameParts, int type)
111 throws IllegalArgumentException, IOException {
112 if (nameParts == null) {
113 throw new IllegalArgumentException("Null input not allowed");
114 }
115 nameStrings = new String[nameParts.length];
116 System.arraycopy(nameParts, 0, nameStrings, 0, nameParts.length);
117 nameType = type;
118 nameRealm = null;
119 }
120
121 public PrincipalName(String[] nameParts) throws IOException {
122 this(nameParts, KRB_NT_UNKNOWN);
123 }
124
125 public Object clone() {
126 try {
127 PrincipalName pName = (PrincipalName) super.clone();
128
129 if (nameStrings != null) {
130 pName.nameStrings = nameStrings.clone();
131 }
132 if (nameRealm != null) {
133 pName.nameRealm = (Realm)nameRealm.clone();
134 }
135 return pName;
136 } catch (CloneNotSupportedException ex) {
137 throw new AssertionError("Should never happen");
138 }
139 }
140
141
142
143
144
145
146 public boolean equals(Object o) {
147 if (o instanceof PrincipalName)
148 return equals((PrincipalName)o);
149 else
150 return false;
151 }
152
153 public boolean equals(PrincipalName other) {
154
155
156 if (!equalsWithoutRealm(other)) {
157 return false;
158 }
159
160 if ((nameRealm != null && other.nameRealm == null) ||
161 (nameRealm == null && other.nameRealm != null)) {
162 return false;
163 }
164
165 if (nameRealm != null && other.nameRealm != null) {
166 if (!nameRealm.equals(other.nameRealm)) {
167 return false;
168 }
169 }
170
171 return true;
172 }
173
174 boolean equalsWithoutRealm(PrincipalName other) {
175
176
177 if (nameType != KRB_NT_UNKNOWN &&
178 other.nameType != KRB_NT_UNKNOWN &&
179 nameType != other.nameType)
180 return false;
181
182 if ((nameStrings != null && other.nameStrings == null) ||
183 (nameStrings == null && other.nameStrings != null))
184 return false;
185
186 if (nameStrings != null && other.nameStrings != null) {
187 if (nameStrings.length != other.nameStrings.length)
188 return false;
189 for (int i = 0; i < nameStrings.length; i++)
190 if (!nameStrings[i].equals(other.nameStrings[i]))
191 return false;
192 }
193
194 return true;
195
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 public PrincipalName(DerValue encoding)
225 throws Asn1Exception, IOException {
226 nameRealm = null;
227 DerValue der;
228 if (encoding == null) {
229 throw new IllegalArgumentException("Null input not allowed");
230 }
231 if (encoding.getTag() != DerValue.tag_Sequence) {
232 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
233 }
234 der = encoding.getData().getDerValue();
235 if ((der.getTag() & 0x1F) == 0x00) {
236 BigInteger bint = der.getData().getBigInteger();
237 nameType = bint.intValue();
238 } else {
239 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
240 }
241 der = encoding.getData().getDerValue();
242 if ((der.getTag() & 0x01F) == 0x01) {
243 DerValue subDer = der.getData().getDerValue();
244 if (subDer.getTag() != DerValue.tag_SequenceOf) {
245 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
246 }
247 Vector<String> v = new Vector<>();
248 DerValue subSubDer;
249 while(subDer.getData().available() > 0) {
250 subSubDer = subDer.getData().getDerValue();
251 v.addElement(new KerberosString(subSubDer).toString());
252 }
253 if (v.size() > 0) {
254 nameStrings = new String[v.size()];
255 v.copyInto(nameStrings);
256 } else {
257 nameStrings = new String[] {""};
258 }
259 } else {
260 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
261 }
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 public static PrincipalName parse(DerInputStream data,
279 byte explicitTag, boolean
280 optional)
281 throws Asn1Exception, IOException {
282
283 if ((optional) && (((byte)data.peekByte() & (byte)0x1F) !=
284 explicitTag))
285 return null;
286 DerValue der = data.getDerValue();
287 if (explicitTag != (der.getTag() & (byte)0x1F))
288 throw new Asn1Exception(Krb5.ASN1_BAD_ID);
289 else {
290 DerValue subDer = der.getData().getDerValue();
291 return new PrincipalName(subDer);
292 }
293 }
294
295
296
297
298
299
300 protected static String[] parseName(String name) {
301
302 Vector<String> tempStrings = new Vector<>();
303 String temp = name;
304 int i = 0;
305 int componentStart = 0;
306 String component;
307
308 while (i < temp.length()) {
309 if (temp.charAt(i) == NAME_COMPONENT_SEPARATOR) {
310
311
312
313
314 if (i > 0 && temp.charAt(i - 1) == '\\') {
315 temp = temp.substring(0, i - 1) +
316 temp.substring(i, temp.length());
317 continue;
318 }
319 else {
320 if (componentStart < i) {
321 component = temp.substring(componentStart, i);
322 tempStrings.addElement(component);
323 }
324 componentStart = i + 1;
325 }
326 } else
327 if (temp.charAt(i) == NAME_REALM_SEPARATOR) {
328
329
330
331
332 if (i > 0 && temp.charAt(i - 1) == '\\') {
333 temp = temp.substring(0, i - 1) +
334 temp.substring(i, temp.length());
335 continue;
336 } else {
337 if (componentStart < i) {
338 component = temp.substring(componentStart, i);
339 tempStrings.addElement(component);
340 }
341 componentStart = i + 1;
342 break;
343 }
344 }
345 i++;
346 }
347
348 if (i == temp.length())
349 if (componentStart < i) {
350 component = temp.substring(componentStart, i);
351 tempStrings.addElement(component);
352 }
353
354 String[] result = new String[tempStrings.size()];
355 tempStrings.copyInto(result);
356 return result;
357 }
358
359 public PrincipalName(String name, int type)
360 throws RealmException {
361 if (name == null) {
362 throw new IllegalArgumentException("Null name not allowed");
363 }
364 String[] nameParts = parseName(name);
365 Realm tempRealm = null;
366 String realmString = Realm.parseRealmAtSeparator(name);
367
368 if (realmString == null) {
369 try {
370 Config config = Config.getInstance();
371 realmString = config.getDefaultRealm();
372 } catch (KrbException e) {
373 RealmException re =
374 new RealmException(e.getMessage());
375 re.initCause(e);
376 throw re;
377 }
378 }
379
380 if (realmString != null)
381 tempRealm = new Realm(realmString);
382
383 switch (type) {
384 case KRB_NT_SRV_HST:
385 if (nameParts.length >= 2) {
386 String hostName = nameParts[1];
387 try {
388
389
390
391
392 String canonicalized = (InetAddress.getByName(hostName)).
393 getCanonicalHostName();
394
395
396
397
398 if (canonicalized.toLowerCase()
399 .startsWith(hostName.toLowerCase()+".")) {
400 hostName = canonicalized;
401 }
402 } catch (UnknownHostException e) {
403
404 }
405 nameParts[1] = hostName.toLowerCase();
406 }
407 nameStrings = nameParts;
408 nameType = type;
409
410
411
412
413
414
415
416 String mapRealm = mapHostToRealm(nameParts[1]);
417 if (mapRealm != null) {
418 nameRealm = new Realm(mapRealm);
419 } else {
420 nameRealm = tempRealm;
421 }
422 break;
423 case KRB_NT_UNKNOWN:
424 case KRB_NT_PRINCIPAL:
425 case KRB_NT_SRV_INST:
426 case KRB_NT_SRV_XHST:
427 case KRB_NT_UID:
428 nameStrings = nameParts;
429 nameType = type;
430 nameRealm = tempRealm;
431 break;
432 default:
433 throw new IllegalArgumentException("Illegal name type");
434 }
435 }
436
437 public PrincipalName(String name) throws RealmException {
438 this(name, KRB_NT_UNKNOWN);
439 }
440
441 public PrincipalName(String name, String realm) throws RealmException {
442 this(name, KRB_NT_UNKNOWN);
443 nameRealm = new Realm(realm);
444 }
445
446 public String getRealmAsString() {
447 return getRealmString();
448 }
449
450 public String getPrincipalNameAsString() {
451 StringBuffer temp = new StringBuffer(nameStrings[0]);
452 for (int i = 1; i < nameStrings.length; i++)
453 temp.append(nameStrings[i]);
454 return temp.toString();
455 }
456
457 public int hashCode() {
458 return toString().hashCode();
459 }
460
461 public String getName() {
462 return toString();
463 }
464
465 public int getNameType() {
466 return nameType;
467 }
468
469 public String[] getNameStrings() {
470 return nameStrings;
471 }
472
473 public byte[][] toByteArray() {
474 byte[][] result = new byte[nameStrings.length][];
475 for (int i = 0; i < nameStrings.length; i++) {
476 result[i] = new byte[nameStrings[i].length()];
477 result[i] = nameStrings[i].getBytes();
478 }
479 return result;
480 }
481
482 public String getRealmString() {
483 if (nameRealm != null)
484 return nameRealm.toString();
485 return null;
486 }
487
488 public Realm getRealm() {
489 return nameRealm;
490 }
491
492 public void setRealm(Realm new_nameRealm) throws RealmException {
493 nameRealm = new_nameRealm;
494 }
495
496 public void setRealm(String realmsString) throws RealmException {
497 nameRealm = new Realm(realmsString);
498 }
499
500 public String getSalt() {
501 if (salt == null) {
502 StringBuffer salt = new StringBuffer();
503 if (nameRealm != null) {
504 salt.append(nameRealm.toString());
505 }
506 for (int i = 0; i < nameStrings.length; i++) {
507 salt.append(nameStrings[i]);
508 }
509 return salt.toString();
510 }
511 return salt;
512 }
513
514 public String toString() {
515 StringBuffer str = new StringBuffer();
516 for (int i = 0; i < nameStrings.length; i++) {
517 if (i > 0)
518 str.append("/");
519 str.append(nameStrings[i]);
520 }
521 if (nameRealm != null) {
522 str.append("@");
523 str.append(nameRealm.toString());
524 }
525
526 return str.toString();
527 }
528
529 public String getNameString() {
530 StringBuffer str = new StringBuffer();
531 for (int i = 0; i < nameStrings.length; i++) {
532 if (i > 0)
533 str.append("/");
534 str.append(nameStrings[i]);
535 }
536 return str.toString();
537 }
538
539
540
541
542
543
544
545
546 public byte[] asn1Encode() throws Asn1Exception, IOException {
547 DerOutputStream bytes = new DerOutputStream();
548 DerOutputStream temp = new DerOutputStream();
549 BigInteger bint = BigInteger.valueOf(this.nameType);
550 temp.putInteger(bint);
551 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
552 temp = new DerOutputStream();
553 DerValue der[] = new DerValue[nameStrings.length];
554 for (int i = 0; i < nameStrings.length; i++) {
555 der[i] = new KerberosString(nameStrings[i]).toDerValue();
556 }
557 temp.putSequence(der);
558 bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), temp);
559 temp = new DerOutputStream();
560 temp.write(DerValue.tag_Sequence, bytes);
561 return temp.toByteArray();
562 }
563
564
565
566
567
568
569
570
571
572 public boolean match(PrincipalName pname) {
573 boolean matched = true;
574
575
576
577
578 if ((this.nameRealm != null) && (pname.nameRealm != null)) {
579 if (!(this.nameRealm.toString().equalsIgnoreCase(pname.nameRealm.toString()))) {
580 matched = false;
581 }
582 }
583 if (this.nameStrings.length != pname.nameStrings.length) {
584 matched = false;
585 } else {
586 for (int i = 0; i < this.nameStrings.length; i++) {
587 if (!(this.nameStrings[i].equalsIgnoreCase(pname.nameStrings[i]))) {
588 matched = false;
589 }
590 }
591 }
592 return matched;
593 }
594
595
596
597
598
599
600
601
602 public void writePrincipal(CCacheOutputStream cos) throws IOException {
603 cos.write32(nameType);
604 cos.write32(nameStrings.length);
605 if (nameRealm != null) {
606 byte[] realmBytes = null;
607 realmBytes = nameRealm.toString().getBytes();
608 cos.write32(realmBytes.length);
609 cos.write(realmBytes, 0, realmBytes.length);
610 }
611 byte[] bytes = null;
612 for (int i = 0; i < nameStrings.length; i++) {
613 bytes = nameStrings[i].getBytes();
614 cos.write32(bytes.length);
615 cos.write(bytes, 0, bytes.length);
616 }
617 }
618
619
620
621
622
623
624
625
626
627 protected PrincipalName(String primary, String instance, String realm,
628 int type)
629 throws KrbException {
630
631 if (type != KRB_NT_SRV_INST) {
632 throw new KrbException(Krb5.KRB_ERR_GENERIC, "Bad name type");
633 }
634
635 String[] nParts = new String[2];
636 nParts[0] = primary;
637 nParts[1] = instance;
638
639 this.nameStrings = nParts;
640 this.nameRealm = new Realm(realm);
641 this.nameType = type;
642 }
643
644
645
646
647
648
649
650
651
652 public String getInstanceComponent()
653 {
654 if (nameStrings != null && nameStrings.length >= 2)
655 {
656 return new String(nameStrings[1]);
657 }
658
659 return null;
660 }
661
662 static String mapHostToRealm(String name) {
663 String result = null;
664 try {
665 String subname = null;
666 Config c = Config.getInstance();
667 if ((result = c.getDefault(name, "domain_realm")) != null)
668 return result;
669 else {
670 for (int i = 1; i < name.length(); i++) {
671 if ((name.charAt(i) == '.') && (i != name.length() - 1)) {
672 subname = name.substring(i);
673 result = c.getDefault(subname, "domain_realm");
674 if (result != null) {
675 break;
676 }
677 else {
678 subname = name.substring(i + 1);
679 result = c.getDefault(subname, "domain_realm");
680 if (result != null) {
681 break;
682 }
683 }
684 }
685 }
686 }
687 } catch (KrbException e) {
688 }
689 return result;
690 }
691
692 }